
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

/**
 * A class which represents a bus to be driven.
 *
 * A bus has an id and bus number. By default, a bus has
 * no driver, but a driver id can be set to the bus.
 *
 * @version 1.0
 */
public class Bus
{
    //The id of this bus, used for DB queries.
    private int busID;
    //The route this bus is currently on
    private Route route;
    //The driver of a particular bus
    private Driver driver;
    //The shifts this bus has worked
    private ArrayList<BusShift> shifts;
    
    
    /**
     * Constructs a bus with a given bus number.
     * 
     * The bus number is used to find the ID of the bus for
     * future queries.
     * @param busNumber A string representation of the bus
     */
    public Bus(String busNumber)
    {
        this.busID = BusInfo.findBus(busNumber);
        this.shifts = new ArrayList<BusShift>();
    }
    
    /**
     * Constructs a bus with a given bus number and route
     */
    public Bus(String busNumber, Route route)
    {
        this(busNumber);
        this.route = route;
    }

    /**
     * Constructs a bus with the given bus ID and route
     * @param busID The bus ID
     * @param route The route this bus will travel on
     */
    public Bus(int busID, Route route)
    {
        this.busID = busID;
        this.route = route;
        this.shifts = new ArrayList<BusShift>();
    }

    /**
     * Constructs a bus with a given bus ID and route ID
     * @param busID The bus ID
     * @param routeID The ID of a route
     */
    public Bus(int busID, int routeID)
    {
        this.busID = busID;
        this.route = new Route(routeID);
        this.shifts = new ArrayList<BusShift>();
    }

    /**
     * Constructs a bus with a bus ID
     *
     * @param busID The ID of the bus
     */
    public Bus(int busID)
    {
        this.busID = busID;
        this.shifts = new ArrayList<BusShift>();
    }

    /**
     *
     * @return The route this bus is currently set to
     */
    public Route getRoute()
    {
        return this.route;
    }

    /**
     * Sets the route this bus is set to
     * @param newRoute The new route the bus should be on
     */
    public void setRoute(Route newRoute)
    {
        this.route = newRoute;
    }

    /**
     * Set the driver of this bus
     * @param newDriver The driver of this bus currently
     */
    public void setDriver(Driver newDriver)
    {
        this.driver = newDriver;      
    }
    
    public void addService(Service service)
    {
        BusShift newShift = new BusShift(service, this);
        this.shifts.add(newShift);
    }
    
    /**
     * Set the last time a bus was used for a shift
     * @param newWorkedShift The end of the newest worked shift.
     */
    public void setLastWorkedShift(BusShift shift)
    {
        this.shifts.add(shift);
        //System.out.println("Last worked shift: " + this.lastWorkedShift.get(Calendar.HOUR) + ":" + this.lastWorkedShift.get(Calendar.MINUTE));
    }
    
    /**
     * Get whether a bus is available on a particular date.
     * @param Shift The shift to check availability with
     * @return true if the bus is available on that date, false otherwise
     */
    public boolean getAvailabilityOn(BusShift shift)
    {
        //return BusInfo.isAvailable(this.busID, date);
        
        //System.out.println("Try to assign to: " + date.get(Calendar.HOUR) + ":" + date.get(Calendar.MINUTE));
        /*if (this.lastWorkedShift == null)
            System.out.println("Checking with: null");
        else
            System.out.println("Checking with: " + this.lastWorkedShift.get(Calendar.HOUR) + ":" + this.lastWorkedShift.get(Calendar.MINUTE));*/
        //If no last worked shift set, we can be set to a service
        if (this.shifts.isEmpty())
            return true;
        else
        {
            Iterator<BusShift> shiftIter = shifts.iterator();
            while (shiftIter.hasNext())
            {
                if (shiftIter.next().isShiftIn(shift))
                    return false;
            }
            
            return true;
        }
    }

    /**
     * Returns the 5 figure fleet number used to identify this bus.
     * @return A String representation of the fleet number for this bus.
     */
    public String getFleetNumber()
    {
        return BusInfo.busNumber(this.busID);
    }
    
    /**
     * Adds a shift to the list of shifts this bus has to work.
     * @param shift The shift to add.
     */
    public void addShift(BusShift shift)
    {
        this.shifts.add(shift);
    }
    
    /**
     * Get all the shifts this bus is currently working.
     * @return An ArrayList representing all shifts the bus is working on.
     */
    public ArrayList<BusShift> getShifts()
    {
        return this.shifts;
    }
    
    /**
     * Set whether a bus is available on a particular date.
     * @param isAvailable true if the bus is set to available, false otherwise
     * @param date The date to set availability on
     */
    public void setAvailabilityOn(boolean isAvailable, Date date)
    {
        BusInfo.setAvailable(this.busID, date, isAvailable);
    }
    
    
    @Override
    public String toString(){
        return "busID: " + busID;
    }

    public int getBusID()
    {
        return this.busID;
    }

    /**
     * Get all buses within the IBMS database.
     * @return An ArrayList of all buses within the database.
     */
    public static ArrayList<Bus> getAllBuses(){
        int[] busIDs = BusInfo.getBuses();
        ArrayList<Bus> buses = new ArrayList<Bus>();

        for (int i = 0; i < busIDs.length; i++)
        {
                buses.add(new Bus(busIDs[i]));
        }

        return buses;
    }



    /**
     * Find all buses available on a given date
     * @param date The date to find buses for
     * @return All buses available on a given date
     */
    public static ArrayList<Bus> getBusesAvailableOn(Date date)
    {
        int[] busIDs = BusInfo.getBuses();
        ArrayList<Bus> buses = new ArrayList<Bus>();

        for (int i = 0; i < busIDs.length; i++)
        {
            if (BusInfo.isAvailable(busIDs[i], date))
                buses.add(new Bus(busIDs[i]));
        }

        return buses;
    }

    /**
     * Find all buses available today
     * @return All buses available today
     */
    public static ArrayList<Bus> getBusesAvailableToday()
    {
        int[] busIDs = BusInfo.getBuses();
        ArrayList<Bus> buses = new ArrayList<Bus>();

        for (int i = 0; i < busIDs.length; i++)
        {
            if (BusInfo.isAvailable(busIDs[i]))
                buses.add(new Bus(busIDs[i]));
        }

        return buses;
    }

    public static void main(String[] args){
        database.openBusDatabase();
        /*Bus bus = new Bus(565);
        Service s = new Service(TimetableInfo.timetableKind.weekday, 6477, 17, new Route(67), Calendar.getInstance());
        s.assignBus(bus);
        System.out.println(s.isAvailableForService(bus));*/
        
        /*Date date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        BusInfo.setAvailable(565, date, false);
        System.out.println(BusInfo.isAvailable(565, date));*/
        
    }



}
